﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace XYZshell.Game.CardGameEngine
{
	/// <summary>
	/// 游戏实体对象,所有游戏实体类的基类
	/// </summary>
	[Serializable]
	public  class GameObject:INamed
	{
		public string Name
		{
			get;
			set;
		}

		/// <summary>
		/// 根据属性名获得对应属性的值
		/// </summary>
		/// <param name="name">属性名</param>
		/// <returns>对应属性的值</returns>
		public virtual object   GetValue(string name)
		{
			return  this.GetType().GetProperty( name ).GetValue( this, null );
		}
		/// <summary>
		/// 设置指定属性名的属性值
		/// </summary>
		/// <param name="name">属性名</param>
		/// <param name="value">属性的值</param>
		public virtual void  SetValue(string name,object value)
		{
			this.GetType().GetProperty( name ).SetValue( this, value, null );
		}

		public virtual void Invoke( string funName )
		{
			Invoke( funName, new object[]{} );
		}

		public virtual void Invoke( string funName ,object[] parameters )
		{
			
			this.GetType().GetMethod( funName ).Invoke( this, parameters );
		}

		#region 动态事件注册(参见 http://www.cnblogs.com/daxnet/archive/2010/03/19/1689838.html)

		/// <summary>
		/// 事件处理程序
		/// </summary>
		/// <typeparam name="T">继承自EventArgs的事件参数</typeparam>
		/// <param name="sender">事件发出者</param>
		/// <param name="eventArgs">事件参数</param>
		protected virtual void DoTrigger<T>( object sender, T eventArgs ) where T : System.EventArgs
		{
			//this.btnNext.Enabled = true;
		}

		/// <summary>
		/// 获得事件的参数类型
		/// </summary>
		/// <param name="d">事件委托</param>
		/// <returns>参数类型数组</returns>
		private Type[] GetDelegateParameterTypes( Type d )
		{
			if (d.BaseType != typeof( MulticastDelegate ))
			{
				throw new InvalidOperationException( "Not a delegate." );
			}

			MethodInfo invoke = d.GetMethod( "Invoke" );
			if (invoke == null)
			{
				throw new InvalidOperationException( "Not a delegate." );
			}

			ParameterInfo[] parameters = invoke.GetParameters();
			Type[] typeParameters = new Type[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				typeParameters[i] = parameters[i].ParameterType;
			}

			return typeParameters;
		}


		/// <summary>
		/// 获得事件的委托
		/// </summary>
		/// <param name="sender">事件发出者</param>
		/// <param name="eventInfo">事件信息</param>
		/// <returns>事件委托</returns>
		private Delegate GetEventHandler( object sender, EventInfo eventInfo )
		{
			try
			{
				if (eventInfo == null)
					throw new Exception( string.Format( "Unable to find an event named '{0}' on the control '{1}'.",
						eventInfo.Name, sender ) );
				Type[] delegateParameters = this.GetDelegateParameterTypes( eventInfo.EventHandlerType );
				if (delegateParameters == null ||
					delegateParameters.Length != 2)
					throw new InvalidOperationException( string.Format( "Event '{0}' is not valid.", eventInfo.Name ) );
				Type eventArgsType = delegateParameters[1];

				MethodInfo doEventMethod = this.GetType().GetMethod( "DoTrigger",
					BindingFlags.NonPublic | BindingFlags.Instance );

				if (doEventMethod == null)
					throw new Exception( "DoTrigger method doesn't exist." );
				if (!doEventMethod.IsGenericMethod)
					throw new Exception( "DoTrigger method is not a generic method." );
				MethodInfo concreteDoEventMethod = doEventMethod.MakeGenericMethod( eventArgsType );
				Delegate d = Delegate.CreateDelegate( eventInfo.EventHandlerType, this, concreteDoEventMethod );
				return d;
			}
			catch
			{
				throw;
			}
		}

		/// <summary>
		/// 动态注册事件
		/// </summary>
		/// <param name="sender">事件的发出者</param>
		/// <param name="eventName">事件的名称</param>
		public void RegisterTrigger( object sender, string eventName )
		{
			try
			{
				EventInfo eventInfo = sender.GetType().GetEvent( eventName,
					BindingFlags.Public | BindingFlags.Instance );

				Delegate d = this.GetEventHandler( sender, eventInfo );
				eventInfo.AddEventHandler( sender, d );
			}
			catch
			{
				throw;
			}
		}

		#endregion
	}
}
